/*
 * Copyright 2011 Clean GWT
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.cleangwt.gadget.client.phone;

import com.cleangwt.bootstrap.client.style.Forms;
import com.cleangwt.user.client.ui.FocusGroup;
import com.cleangwt.user.client.ui.TextBox;
import com.cleangwt.validation.client.Checks;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.WhiteSpace;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.HasValue;

/**
 * Custom phone number field.
 * 
 * @author Jess
 * @version 1.0
 * @since 1.0
 */
public class PhoneField extends FlowPanel implements HasEnabled, Focusable, HasValue<String> {
  public enum PhoneType {
    EXT, HOUSE, MOBILE
  };

  private boolean valueChangeInitialized;

  private TextBox txtfAreaCode;
  private TextBox txtfExt;
  private TextBox txtfPhoneNo = new TextBox();

  public PhoneField(final PhoneType phoneType) {
    this.setStyleName(Forms.INLINE_STYLE);
    txtfPhoneNo.setStyleName(Forms.FORM_CONTROL_STYLE);
    if (phoneType == PhoneType.HOUSE) {
      createAreaCodeField();
      add(txtfAreaCode);
      getElement().appendChild(Document.get().createTextNode("-"));
      add(txtfPhoneNo);
      txtfPhoneNo.setWidth("106px");
      txtfPhoneNo.setMaxLength(8);
    } else if (phoneType == PhoneType.MOBILE) {
      add(txtfPhoneNo);
      txtfPhoneNo.setWidth("130px");
      txtfPhoneNo.setMaxLength(10);
    } else if (phoneType == PhoneType.EXT) {
      createAreaCodeField();
      createExtField();
      add(txtfAreaCode);
      getElement().appendChild(Document.get().createTextNode("-"));
      add(txtfPhoneNo);
      getElement().appendChild(Document.get().createTextNode("#"));
      add(txtfExt);
      txtfPhoneNo.setWidth("106px");
      txtfPhoneNo.setMaxLength(8);
    }

    this.getElement().getStyle().setDisplay(Display.INLINE_BLOCK);
    this.getElement().getStyle().setWhiteSpace(WhiteSpace.NOWRAP);
  }

  @Override
  public void addStyleName(String style) {
    if (txtfAreaCode != null) {
      txtfAreaCode.addStyleName(style);
    }
    txtfPhoneNo.addStyleName(style);
    if (txtfExt != null) {
      txtfExt.addStyleName(style);
    }
  }

  @Override
  public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
    if (!valueChangeInitialized) {
      valueChangeInitialized = true;
      FocusGroup<String> focusGroup = new FocusGroup<String>(this);
      focusGroup.addFocusable(txtfAreaCode);
      focusGroup.addFocusable(txtfPhoneNo);
      focusGroup.addFocusable(txtfExt);
    }
    return this.addHandler(handler, ValueChangeEvent.getType());
  }

  private void createAreaCodeField() {
    txtfAreaCode = new TextBox();
    txtfAreaCode.setStyleName(Forms.FORM_CONTROL_STYLE);
    txtfAreaCode.setMaxLength(4);
    txtfAreaCode.setWidth("64px");
  }

  private void createExtField() {
    txtfExt = new TextBox();
    txtfExt.setStyleName(Forms.FORM_CONTROL_STYLE);
    txtfExt.setMaxLength(10);
    txtfExt.setWidth("64px");
  }

  public String getPlainValue() {
    String value = "";
    if (txtfAreaCode != null) {
      value += txtfAreaCode.getValue();
    }
    value += txtfPhoneNo.getValue();
    if (txtfPhoneNo != null) {
      value += txtfPhoneNo.getValue();
    }
    return value;
  }

  @Override
  public int getTabIndex() {
    return txtfAreaCode == null ? txtfPhoneNo.getTabIndex() : txtfAreaCode.getTabIndex();
  }

  @Override
  public String getValue() {
    String value = "";
    if (txtfAreaCode != null) {
      value += (Checks.isEmpty(txtfAreaCode.getValue()) ? "" : txtfAreaCode.getValue() + "-");
    }
    value += txtfPhoneNo.getValue();
    if (txtfExt != null) {
      value += Checks.isEmpty(txtfExt.getValue()) ? "" : ("#" + txtfExt.getValue());
    }
    return value;
  }

  @Override
  public boolean isEnabled() {
    return txtfPhoneNo.isEnabled();
  }

  @Override
  public void removeStyleName(String style) {
    if (txtfAreaCode != null) {
      txtfAreaCode.removeStyleName(style);
    }
    txtfPhoneNo.removeStyleName(style);
    if (txtfExt != null) {
      txtfExt.removeStyleName(style);
    }
  }

  @Override
  public void setAccessKey(char key) {
    if (txtfAreaCode == null) {
      txtfPhoneNo.setAccessKey(key);
    } else {
      txtfAreaCode.setAccessKey(key);
    }
  }

  @Override
  public void setEnabled(boolean enabled) {
    txtfAreaCode.setEnabled(enabled);
    txtfPhoneNo.setEnabled(enabled);
    txtfExt.setEnabled(enabled);
  }

  @Override
  public void setFocus(boolean focused) {
    if (txtfAreaCode == null) {
      txtfPhoneNo.setFocus(focused);
    } else {
      txtfAreaCode.setFocus(focused);
    }
  }

  @Override
  public void setTabIndex(int index) {
    if (txtfAreaCode == null) {
      txtfPhoneNo.setTabIndex(index);
    } else {
      txtfAreaCode.setTabIndex(index);
    }
  }

  @Override
  public void setValue(String value) {
    setValue(value, false);

  }

  @Override
  public void setValue(String value, boolean fireEvents) {
    String oldValue = getValue();
    if (value != null) {
      int delimiter1 = value.indexOf("-");
      int delimiter2 = value.indexOf("#");

      String areaCode = delimiter1 != -1 ? value.substring(0, delimiter1) : "";
      String ext = delimiter2 != -1 ? value.substring(delimiter2 + 1, value.length()) : "";
      String phone = value.replace(areaCode + "-", "").replace("#" + ext, "");

      txtfAreaCode.setValue(areaCode);
      txtfPhoneNo.setValue(phone);
      txtfExt.setValue(ext);
    } else {
      txtfAreaCode.setValue("");
      txtfPhoneNo.setValue("");
      txtfExt.setValue("");
    }
    if (fireEvents) {
      ValueChangeEvent.fireIfNotEqual(this, oldValue, value);
    }
  }
}
